﻿using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Mehdime.Entity;
using WikeSoft.Core;
using WikeSoft.Core.Exception;
using WikeSoft.Core.Extension;
using WikeSoft.Data;
using WikeSoft.Data.Models;
using WikeSoft.Data.Models.Sys;
using WikeSoft.Enterprise.Entities;
using WikeSoft.Enterprise.Enum;
using WikeSoft.Enterprise.Interfaces.Sys;
using WikeSoft.Enterprise.Models.Filters.Sys;
using WikeSoft.Enterprise.Models.Sys;

namespace WikeSoft.Enterprise.AppServices.Sys
{
    /// <summary>
    /// 用户服务
    /// </summary>
    public class UserService : IUserService
    {
        private readonly IMapper _mapper;
        private readonly IDbContextScopeFactory _dbContextScopeFactory;
        private readonly IDepartmentService _departmentService;
        private readonly IKeyValueService _keyValueService;

        public UserService(IMapper mapper, IDbContextScopeFactory dbContextScopeFactory,
            IDepartmentService departmentService, IKeyValueService keyValueService)
        {
            _mapper = mapper;
            _dbContextScopeFactory = dbContextScopeFactory;
            _departmentService = departmentService;
            _keyValueService = keyValueService;
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Add(UserAddModel user)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var userEntity = _mapper.Map<UserAddModel, SysUser>(user);
                userEntity.UserStatus = UserStatus.Enabled;
                userEntity.PassWord = user.PassWord.ToMD5();
                userEntity.PasswordExpirationDate = DateTime.Now;
                
                //处理用户与角色间的关系
                if (user.RoleIds.AnyOne())
                {
                    userEntity.SysRoles = db.SysRoles.Where(x => user.RoleIds.Contains(x.Id)).ToList();
                    //userEntity.ZfPosts = db.ZfPosts.Where(x => x.Id == user.PostId).ToList();
                }

                db.SysUsers.Add(userEntity);
                return scope.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 编辑用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Edit(UserEditModel user)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var userEntity = db.SysUsers.Load(user.Id);
                _mapper.Map(user, userEntity);
                if (user.PassWord.IsNotBlank())
                {
                    userEntity.PassWord = user.PassWord.ToMD5();
                    userEntity.PasswordExpirationDate = DateTime.Now;
                }
                  

                //处理用户与角色间的关系
                var oldRoles = userEntity.SysRoles.ToList();
                if (user.RoleIds.AnyOne())
                {
                    //新增的角色
                    var roles = db.SysRoles.Where(x => user.RoleIds.Contains(x.Id))
                        .ToList()
                        .Where(x => oldRoles.All(r => r.Id != x.Id)).ToList();
                    //删除的角色
                    var deleteRoles = oldRoles.Where(x => !user.RoleIds.Contains(x.Id)).ToList();
                    userEntity.SysRoles.AddRange(roles);
                    userEntity.SysRoles.RemoveRange(deleteRoles);
                }
                else
                {
                    userEntity.SysRoles.RemoveRange(oldRoles);
                }
                scope.SaveChanges();
                return true;

            }
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool ChangePassword(ChangePasswordModel model)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var user = db.SysUsers.Load(model.UserId);
                if (user.PassWord != model.OldPassword.ToMD5())
                {
                    throw new TipInfoException("当前密码输入错误");
                }
                if (model.Password != model.ConfirmPassword)
                {
                    throw new TipInfoException("两次输入密码不一致");
                }
                user.PassWord = model.Password.ToMD5();
                user.PasswordExpirationDate = DateTime.Now.AddMonths(3);
                return scope.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        public UserEditModel Find(string id)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var userEntity = db.SysUsers.Load(id);
                var department = userEntity.SysDepartment;
                var user = _mapper.Map<SysUser, UserEditModel>(userEntity);
                if (department != null)
                {
                    user.DepartmentName = department.DepartmentName;
                }

                return user;
            }
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="ids">用户id集合</param>
        /// <returns></returns>
        public bool Delete(IList<string> ids)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var users = db.SysUsers.Where(x => ids.Contains(x.Id)).ToList();

                users.ForEach(c =>
                {
                    c.IsDelete = true;
                });

                return scope.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 验证用户名是否重复
        /// </summary>
        /// <param name="userId">用户id，可以为空，为空表示添加</param>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        public bool IsExists(string userId, string userName)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var query = db.SysUsers.Where(x => x.UserName == userName && x.IsDelete == false);
                if (userId.IsNotBlank())
                {
                    query = query.Where(x => x.Id != userId);
                }
                return query.Any();
            }
        }

        /// <summary>
        /// 验证员工编号是否重复
        /// </summary>
        /// <param name="userId">用户id，可以为空，为空表示添加</param>
        /// <param name="userCode">员工编号</param>
        /// <returns></returns>
        public bool IsExsitUserCode(string userId, string userCode)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var query = db.SysUsers.Where(x => x.UserCode == userCode && x.IsDelete == false);
                if (userId.IsNotBlank())
                {
                    query = query.Where(x => x.Id != userId);
                }
                return query.Any();
            }
        }

        /// <summary>
        /// 验证用户密码是否和上一次密码一样
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <param name="password">新密码</param>
        /// <returns></returns>
        public bool IsOldPassword(string userId, string password)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                password = password.ToMD5();
                return db.SysUsers.Any(x => x.Id == userId && x.PassWord == password);
            }
        }

     

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public LoginModel Login(LoginModel model)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var user = db.SysUsers.FirstOrDefault(x => x.UserName == model.UserName && x.IsDelete==false);
                if (user == null)
                {
                    model.LoginError = "登录名不存在";
                }
                else if (user.PassWord != model.Password.ToMD5())
                {
                    model.LoginError = "登录密码错误";
                }
                else if (user.UserStatus == UserStatus.Disabled)
                {
                    model.LoginError = "用户已离职";
                }
                else
                {
                    model.LoginSuccess = true;
                    model.UserId = user.Id;
                    model.TrueName = user.TrueName;
                    model.Roles = user.SysRoles.ToList();
                }
                return model;
            }
        }

        /// <summary>
        /// 分页查询用户信息
        /// </summary>
        /// <param name="filters"></param>
        /// <returns></returns>
        public PagedResult<UserModel> GetUsers(UserFilter filters)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var query = db.SysUsers.Where(x => x.IsDelete == false);
                if (filters.keywords.IsNotBlank())
                {
                    query = query.Where(x => x.UserName.Contains(filters.keywords) ||
                                             x.TrueName.Contains(filters.keywords));
                }
                if (filters.DepartmentId.IsNotBlank())
                {
                    query = query.Where(x => x.DepartmentId == filters.DepartmentId);
                }

                if (filters.TrueName.IsNotBlank())
                {
                    query = query.Where(x => x.TrueName.Contains(filters.TrueName));
                }
                if (filters.UserName.IsNotBlank())
                {
                    query = query.Where(x => x.UserName.Contains(filters.UserName));
                }
                return query.OrderByCustom(filters.sidx, filters.sord)
                    .Select(item => new UserModel
                    {
                        Id = item.Id,
                        TrueName = item.TrueName,
                        UserName = item.UserName,
                        Email = item.Email,
                        Mobile = item.Mobile,
                        UserStatus = item.UserStatus,
                        DepartmentName = item.SysDepartment.DepartmentName,
                        UserCode = item.UserCode

                    }).Paging(filters.page, filters.rows);
            }
        }

        /// <summary>
        /// 检查用户密码是否过期
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <returns></returns>
        public bool IsPasswordExpirated(string userId)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                return
                    db.SysUsers.Any(
                        x =>
                            x.Id == userId && x.PasswordExpirationDate != null &&
                            x.PasswordExpirationDate < DateTime.Now);
            }
        }

        /// <summary>
        /// 得到上级
        /// </summary>
        /// <param name="getLoginUserId"></param>
        /// <returns></returns>
        public UserModel GetLeadShip(string getLoginUserId)
        {
            List<DepartmentModel> departments = _departmentService.GetParentDepartmentByUserId(getLoginUserId, true);
            string[] departmentGuids = departments.Where(x => x.Id!=null || x.Id!=string.Empty).Select(x => x.Id).ToArray();
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var me = db.SysUsers.Find(getLoginUserId);
                if (me == null)
                {
                    throw new TipInfoException("找不到用户信息");
                }

                //一般员工
                string[] normalRole =
                    _keyValueService.GetValue("normalRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //主管
                string[] chargeRole =
                     _keyValueService.GetValue("chargeRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //经理
                string[] managerRole =
                     _keyValueService.GetValue("managerRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //总监 
                string[] chiefRole =
                     _keyValueService.GetValue("chiefRole").Split(';')
                        .Select(x => x)
                        .ToArray();

                if (me.SysRoles.Count(x => normalRole.Contains(x.Id)) > 0) //一般员工
                {
                    var leader =
                        db.SysUsers.FirstOrDefault(
                            x =>
                                x.DepartmentId != null && departmentGuids.Contains(x.DepartmentId) &&
                                x.SysRoles.Any(s => chargeRole.Contains(s.Id)));
                    return _mapper.Map<SysUser, UserModel>(leader);
                }

                else if (me.SysRoles.Count(x => chargeRole.Contains(x.Id)) > 0) //主管
                {
                    var leader =
                        db.SysUsers.FirstOrDefault(
                            x =>
                                x.DepartmentId != null && departmentGuids.Contains(x.DepartmentId) &&
                                x.SysRoles.Any(s => managerRole.Contains(s.Id)));
                    return _mapper.Map<SysUser, UserModel>(leader);
                }

                else if (me.SysRoles.Count(x => managerRole.Contains(x.Id)) > 0) //经理
                {
                    var leader =
                        db.SysUsers.FirstOrDefault(
                            x =>
                                x.DepartmentId != null && departmentGuids.Contains(x.DepartmentId) &&
                                x.SysRoles.Any(s => chiefRole.Contains(s.Id)));
                    return _mapper.Map<SysUser, UserModel>(leader);
                }

                return null;

            }
        }

        public bool IsLeader(string userId)
        { 
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var me = db.SysUsers.Find(userId);
                if (me == null)
                {
                    throw new TipInfoException("找不到用户信息");
                }

                //一般员工
                string[] normalRole =
                     _keyValueService.GetValue("normalRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //主管
                string[] chargeRole =
                     _keyValueService.GetValue("chargeRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //经理
                string[] managerRole =
                    _keyValueService.GetValue("managerRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                //总监 
                string[] chiefRole =
                    _keyValueService.GetValue("chiefRole").Split(';')
                        .Select(x => x)
                        .ToArray();
                 
                if (me.SysRoles.Count(x => chiefRole.Contains(x.Id)) > 0) //总监
                {
                    return true;
                }
                else if (me.SysRoles.Count(x => managerRole.Contains(x.Id)) > 0) //经理
                {
                    return true;
                }
                else if (me.SysRoles.Count(x => chargeRole.Contains(x.Id)) > 0) //主管
                {
                    return true;
                }
                else if (me.SysRoles.Count(x => normalRole.Contains(x.Id)) > 0) //一般员工
                {
                    return false;
                }

                return false;

            }
        }

        public List<UserModel> GetSubUsers(string userId)
        { 
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
              
                var sysUser = db.SysUsers.Find(userId);
                if (sysUser != null)
                {
                    var pathCode = sysUser.SysDepartment.PathCode;
                    var userIds = db.SysUsers.Where(c => c.SysDepartment.PathCode.StartsWith(pathCode)).Select(x => x.Id);
                    var query = db.SysUsers.Where(x => userIds.Contains(x.Id));

                    return query.Select(item => new UserModel
                    {
                        Id = item.Id,
                        TrueName = item.TrueName,
                        UserName = item.UserName,
                        Email = item.Email,
                        Mobile = item.Mobile,
                        UserStatus = item.UserStatus,
                        DepartmentName = item.SysDepartment.DepartmentName,
                        UserCode = item.UserCode,
                        IsDelete =  item.IsDelete

                    }).ToList();
                }
               
             
 
            }
            return new List<UserModel>(); 
        }

        public List<UserModel> GetUsersByDepartment(List<string> departments)
        {
            using (var scope = _dbContextScopeFactory.CreateReadOnly())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();

              
                  
                    var query = db.SysUsers.Where(x => departments.Contains(x.DepartmentId));

                    return query.Select(item => new UserModel
                    {
                        Id = item.Id,
                        TrueName = item.TrueName,
                        UserName = item.UserName,
                        Email = item.Email,
                        Mobile = item.Mobile,
                        UserStatus = item.UserStatus,
                        DepartmentName = item.SysDepartment.DepartmentName,
                        UserCode = item.UserCode,
                        IsDelete = item.IsDelete

                    }).ToList();
                


            }
        }
    }
}

